home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sound / vlm5030.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  16KB  |  643 lines

  1. /*
  2.     vlm5030.c
  3.  
  4.     VLM5030 emulator (preliminary)
  5.  
  6.     Written by Tatsuyuki Satoh
  7.  
  8.   note:
  9.     memory read cycle(sampling rate ?) = 122.9u(440clock)
  10.     interpolator (LC8109 = 2.5ms)      = 20 * samples(125us)
  11.     frame time (20ms)                  =  8 * interpolator
  12.  
  13. ----------- command format (Analytical result) ----------
  14.  
  15. 1)end of speech (8bit)
  16. :00000011:
  17.  
  18. 2)silent some frame (8bit)
  19. :????LL01:
  20.  
  21. LL : number of silent frames
  22.    00 = 2 frame
  23.    01 = 4 frame
  24.    10 = 6 frame
  25.    11 = 8 frame
  26.  
  27. 3)play one frame (48bit/frame)
  28. : 1st    :   2nd  :   3rd  :   4th  :  5th   :   6th  :
  29. :EEPPPPP0:99AAAEEE:67778889:44455566:22233334:11111112:
  30.  
  31. energy and pitch bits are MSB first.
  32.  
  33. EEEEE  : energy ( volume 0=off,0x1f=max)
  34. PPPPP  : pitch  (0=noize?, 1=fast,0x1f=slow)
  35. 1111111: stage 1?
  36. 2222   : stage 2?
  37. 3333   : stage 3?
  38. 4444   : stage 4?
  39. 555    : stage 5?
  40. 666    : stage 6?
  41. 777    : stage 7?
  42. 888    : stage 8?
  43. 999    : stage 9?
  44. AAA    : stage 10?
  45.  
  46.  ---------- chirp table information ----------
  47.  
  48. digital filter sampling rate = 88 systemclock = 40.6KHz
  49. sampling clock = 88systemclock(40.6KHz)
  50. one chirp      = 5 sampling clocks = 440systemclock(8.12KHz)
  51.  
  52. chirp  0   : volume 10- 8 : with filter
  53. chirp  1   : volume  8- 6 : with filter
  54. chirp  2   : volume  6- 4 : with filter
  55. chirp  3   : volume   4   : no filter ??
  56. chirp  4- 5: volume  4- 2 : with filter
  57. chirp  6-11: volume  2- 0 : with filter
  58. chirp 12-..: vokume   0   : silent
  59.  
  60.  ---------- pitch table information ----------
  61. 0 = random
  62. 1 = 22stage(2700usec)
  63.  2-09 1stage(120usec)
  64. 0a-11 2stage(240usec)
  65. 12-19 4stage(480usec)
  66. 1A-1E 8stage(960usec)
  67.  
  68. */
  69. #include "driver.h"
  70. #include "vlm5030.h"
  71.  
  72. #define IP_SIZE 20        /* samples per interpolator */
  73. #define FR_SIZE 8        /* interpolator per frame   */
  74.  
  75. static const struct VLM5030interface *intf;
  76.  
  77. static int channel;
  78. static int schannel;
  79.  
  80. static unsigned char *VLM5030_rom;
  81. static int VLM5030_address_mask;
  82. static int VLM5030_address;
  83. static int pin_BSY;
  84. static int pin_ST;
  85. static int pin_RST;
  86. static int latch_data = 0;
  87. static int sampling_mode;
  88.  
  89. static int table_h;
  90.  
  91. #define PH_RESET 0
  92. #define PH_IDLE  1
  93. #define PH_SETUP 2
  94. #define PH_WAIT  3
  95. #define PH_RUN   4
  96. #define PH_STOP  5
  97. static int phase;
  98.  
  99. /* these contain data describing the current and previous voice frames */
  100. static unsigned short old_energy = 0;
  101. static unsigned short old_pitch = 0;
  102. static int old_k[10] = {0,0,0,0,0,0,0,0,0,0};
  103.  
  104. static unsigned short new_energy = 0;
  105. static unsigned short new_pitch = 0;
  106. static int new_k[10] = {0,0,0,0,0,0,0,0,0,0};
  107.  
  108. /* these are all used to contain the current state of the sound generation */
  109. static unsigned short current_energy = 0;
  110. static unsigned short current_pitch = 0;
  111. static int current_k[10] = {0,0,0,0,0,0,0,0,0,0};
  112.  
  113. static unsigned short target_energy = 0;
  114. static unsigned short target_pitch = 0;
  115. static int target_k[10] = {0,0,0,0,0,0,0,0,0,0};
  116.  
  117. static int interp_count = 0;       /* number of interp periods (0-7) */
  118. static int sample_count = 0;       /* sample number within interp (0-19) */
  119. static int pitch_count = 0;
  120.  
  121. static int u[11] = {0,0,0,0,0,0,0,0,0,0,0};
  122. static int x[10] = {0,0,0,0,0,0,0,0,0,0};
  123.  
  124. /* ROM Tables */
  125.  
  126.  
  127. /* This is the energy lookup table */
  128. /* !!!!!!!!!! preliminary !!!!!!!!!! */
  129. static unsigned short energytable[0x20];
  130.  
  131. /* This is the pitch lookup table */
  132. static const unsigned char pitchtable [0x20]=
  133. {
  134.    0,                               /* 0     : random mode */
  135.    22,                              /* 1     : start=22    */
  136.    23, 24, 25, 26, 27, 28, 29, 30,  /*  2- 9 : 1step       */
  137.    32, 34, 36, 38, 40, 42, 44, 46,  /* 10-17 : 2step       */
  138.    50, 54, 58, 62, 66, 70, 74, 78,  /* 18-25 : 4step       */
  139.    86, 94, 102,110,118,             /* 26-30 : 8step       */
  140.    255                              /* 31    : only one time ?? */
  141. };
  142.  
  143. /* These are the reflection coefficient lookup tables */
  144. /* 2's comp. */
  145.  
  146. /* !!!!!!!!!! preliminary !!!!!!!!!! */
  147.  
  148. /* 7bit */
  149. #define K1_RANGE  0x6000
  150. /* 4bit */
  151. #define K2_RANGE  0x4000
  152. #define K3_RANGE  0x6000
  153. #define K4_RANGE  0x4000
  154. /* 3bit */
  155. #define K5_RANGE  0x6000
  156. #define K6_RANGE  0x6000
  157. #define K7_RANGE  0x5000
  158. #define K8_RANGE  0x4000
  159. #define K9_RANGE  0x5000
  160. #define K10_RANGE 0x4000
  161.  
  162. static int k1table[0x80];
  163. static int k2table[0x10];
  164. static int k3table[0x10];
  165. static int k4table[0x10];
  166. static int k5table[0x08];
  167. static int k6table[0x08];
  168. static int k7table[0x08];
  169. static int k8table[0x08];
  170. static int k9table[0x08];
  171. static int k10table[0x08];
  172.  
  173. /* chirp table */
  174. static unsigned char chirptable[12]=
  175. {
  176.   0xff*9/10,
  177.   0xff*7/10,
  178.   0xff*5/10,
  179.   0xff*4/10, /* non digital filter ? */
  180.   0xff*3/10,
  181.   0xff*3/10,
  182.   0xff*1/10,
  183.   0xff*1/10,
  184.   0xff*1/10,
  185.   0xff*1/10,
  186.   0xff*1/10,
  187.   0xff*1/10
  188. };
  189.  
  190. /* interpolation coefficients */
  191. static int interp_coeff[8] = {
  192. //8, 8, 8, 4, 4, 2, 2, 1
  193. 8, 8, 8, 4, 4, 2, 2, 1
  194. };
  195.  
  196. /* //////////////////////////////////////////////////////// */
  197.  
  198. /* check sample file */
  199. static int check_samplefile(int num)
  200. {
  201.     if (Machine->samples == 0) return 0;
  202.     if (Machine->samples->total <= num ) return 0;
  203.     if (Machine->samples->sample[num] == 0) return 0;
  204.     /* sample file is found */
  205.     return 1;
  206. }
  207.  
  208. static int get_bits(int sbit,int bits)
  209. {
  210.     int offset = VLM5030_address + (sbit>>3);
  211.     int data;
  212.  
  213.     data = VLM5030_rom[offset&VLM5030_address_mask] |
  214.            (((int)VLM5030_rom[(offset+1)&VLM5030_address_mask])<<8);
  215.     data >>= sbit;
  216.     data &= (0xff>>(8-bits));
  217.  
  218.     return data;
  219. }
  220.  
  221. /* get next frame */
  222. static int parse_frame (void)
  223. {
  224.     unsigned char cmd;
  225.  
  226.     /* remember previous frame */
  227.     old_energy = new_energy;
  228.     old_pitch = new_pitch;
  229.     memcpy( old_k , new_k , sizeof(old_k) );
  230.     /* command byte check */
  231.     cmd = VLM5030_rom[VLM5030_address&VLM5030_address_mask];
  232.     if( cmd & 0x01 )
  233.     {    /* extend frame */
  234.         new_energy = new_pitch = 0;
  235.         memset( new_k , 0 , sizeof(new_k));
  236.         VLM5030_address++;
  237.         if( cmd & 0x02 )
  238.         {    /* end of speech */
  239.             logerror("VLM5030 %04X end \n",VLM5030_address );
  240.             return 0;
  241.         }
  242.         else
  243.         {    /* silent frame */
  244.             int nums = ( (cmd>>2)+1 )*2;
  245.             logerror("VLM5030 %04X silent %d frame\n",VLM5030_address,nums );
  246.             return nums * FR_SIZE;
  247.         }
  248.     }
  249.     /* normal frame */
  250.  
  251.     new_pitch  = pitchtable[get_bits( 1,5)];
  252.     new_energy = energytable[get_bits( 6,5)] >> 6;
  253.  
  254.     /* 10 K's */
  255.     new_k[9] = k10table[get_bits(11,3)];
  256.     new_k[8] = k9table[get_bits(14,3)];
  257.     new_k[7] = k8table[get_bits(17,3)];
  258.     new_k[6] = k7table[get_bits(20,3)];
  259.     new_k[5] = k6table[get_bits(23,3)];
  260.     new_k[4] = k5table[get_bits(26,3)];
  261.     new_k[3] = k4table[get_bits(29,4)];
  262.     new_k[2] = k3table[get_bits(33,4)];
  263.     new_k[1] = k2table[get_bits(37,4)];
  264.     new_k[0] = k1table[get_bits(41,7)];
  265.  
  266.     VLM5030_address+=6;
  267.     logerror("VLM5030 %04X voice \n",VLM5030_address );
  268.     return FR_SIZE;
  269. }
  270.  
  271. /* decode and buffering data */
  272. static void vlm5030_update_callback(int num,INT16 *buffer, int length)
  273. {
  274.     int buf_count=0;
  275.     int interp_effect;
  276.  
  277.     /* running */
  278.     if( phase == PH_RUN )
  279.     {
  280.         /* playing speech */
  281.         while (length > 0)
  282.         {
  283.             int current_val;
  284.  
  285.             /* check new interpolator or  new frame */
  286.             if( sample_count == 0 )
  287.             {
  288.                 sample_count = IP_SIZE;
  289.                 /* interpolator changes */
  290.                 if ( interp_count == 0 )
  291.                 {
  292.                     /* change to new frame */
  293.                     interp_count = parse_frame(); /* with change phase */
  294.                     if ( interp_count == 0 )
  295.                     {
  296.                         sample_count = 160; /* end -> stop time */
  297.                         phase = PH_STOP;
  298.                         goto phase_stop; /* continue to stop phase */
  299.                     }
  300.                     /* Set old target as new start of frame */
  301.                     current_energy = old_energy;
  302.                     current_pitch = old_pitch;
  303.                     memcpy( current_k , old_k , sizeof(current_k) );
  304.                     /* is this a zero energy frame? */
  305.                     if (current_energy == 0)
  306.                     {
  307.                         /*printf("processing frame: zero energy\n");*/
  308.                         target_energy = 0;
  309.                         target_pitch = current_pitch;
  310.                         memcpy( target_k , current_k , sizeof(target_k) );
  311.                     }
  312.                     else
  313.                     {
  314.                         /*printf("processing frame: Normal\n");*/
  315.                         /*printf("*** Energy = %d\n",current_energy);*/
  316.                         /*printf("proc: %d %d\n",last_fbuf_head,fbuf_head);*/
  317.                         target_energy = new_energy;
  318.                         target_pitch = new_pitch;
  319.                         memcpy( target_k , new_k , sizeof(target_k) );
  320.                     }
  321.                 }
  322.                 /* next interpolator */
  323.                 /* Update values based on step values */
  324.                 /*printf("\n");*/
  325.                 interp_effect = (int)(interp_coeff[(FR_SIZE-1) - (interp_count%FR_SIZE)]);
  326.  
  327.                 current_energy += (target_energy - current_energy) / interp_effect;
  328.                 if (old_pitch != 0)
  329.                     current_pitch += (target_pitch - current_pitch) / interp_effect;
  330.                 /*printf("*** Energy = %d\n",current_energy);*/
  331.                 current_k[0] += (target_k[0] - current_k[0]) / interp_effect;
  332.                 current_k[1] += (target_k[1] - current_k[1]) / interp_effect;
  333.                 current_k[2] += (target_k[2] - current_k[2]) / interp_effect;
  334.                 current_k[3] += (target_k[3] - current_k[3]) / interp_effect;
  335.                 current_k[4] += (target_k[4] - current_k[4]) / interp_effect;
  336.                 current_k[5] += (target_k[5] - current_k[5]) / interp_effect;
  337.                 current_k[6] += (target_k[6] - current_k[6]) / interp_effect;
  338.                 current_k[7] += (target_k[7] - current_k[7]) / interp_effect;
  339.                 current_k[8] += (target_k[8] - current_k[8]) / interp_effect;
  340.                 current_k[9] += (target_k[9] - current_k[9]) / interp_effect;
  341.                 interp_count --;
  342.             }
  343.             /* calcrate digital filter */
  344.             if (old_energy == 0)
  345.             {
  346.                 /* generate silent samples here */
  347.                 current_val = 0x00;
  348.             }
  349.             else if (old_pitch == 0)
  350.             {
  351.                 /* generate unvoiced samples here */
  352.                 int randvol = (rand () % 10);
  353.                 current_val = (randvol * current_energy) / 10;
  354.             }
  355.             else
  356.             {
  357.                 /* generate voiced samples here */
  358.                 if (pitch_count < sizeof (chirptable))
  359.                     current_val = (chirptable[pitch_count] * current_energy) / 256;
  360.                 else
  361.                     current_val = 0x00;
  362.             }
  363.  
  364.             /* Lattice filter here */
  365.             u[10] = current_val;
  366.             u[9] = u[10] - ((current_k[9] * x[9]) / 32768);
  367.             u[8] = u[ 9] - ((current_k[8] * x[8]) / 32768);
  368.             u[7] = u[ 8] - ((current_k[7] * x[7]) / 32768);
  369.             u[6] = u[ 7] - ((current_k[6] * x[6]) / 32768);
  370.             u[5] = u[ 6] - ((current_k[5] * x[5]) / 32768);
  371.             u[4] = u[ 5] - ((current_k[4] * x[4]) / 32768);
  372.             u[3] = u[ 4] - ((current_k[3] * x[3]) / 32768);
  373.             u[2] = u[ 3] - ((current_k[2] * x[2]) / 32768);
  374.             u[1] = u[ 2] - ((current_k[1] * x[1]) / 32768);
  375.             u[0] = u[ 1] - ((current_k[0] * x[0]) / 32768);
  376.  
  377.             x[9] = x[8] + ((current_k[8] * u[8]) / 32768);
  378.             x[8] = x[7] + ((current_k[7] * u[7]) / 32768);
  379.             x[7] = x[6] + ((current_k[6] * u[6]) / 32768);
  380.             x[6] = x[5] + ((current_k[5] * u[5]) / 32768);
  381.             x[5] = x[4] + ((current_k[4] * u[4]) / 32768);
  382.             x[4] = x[3] + ((current_k[3] * u[3]) / 32768);
  383.             x[3] = x[2] + ((current_k[2] * u[2]) / 32768);
  384.             x[2] = x[1] + ((current_k[1] * u[1]) / 32768);
  385.             x[1] = x[0] + ((current_k[0] * u[0]) / 32768);
  386.             x[0] = u[0];
  387.             /* clipping, buffering */
  388.             if (u[0] > 511)
  389.                 buffer[buf_count] = 127<<8;
  390.             else if (u[0] < -512)
  391.                 buffer[buf_count] = -128<<8;
  392.             else
  393.                 buffer[buf_count] = u[0] << 6;
  394.             buf_count++;
  395.  
  396.             /* sample count */
  397.             sample_count--;
  398.             /* pitch */
  399.             pitch_count++;
  400.             if (pitch_count >= current_pitch )
  401.                 pitch_count = 0;
  402.             /* size */
  403.             length--;
  404.         }
  405. /*        return;*/
  406.     }
  407.     /* stop phase */
  408. phase_stop:
  409.     switch( phase )
  410.     {
  411.     case PH_SETUP:
  412.         sample_count -= length;
  413.         if( sample_count <= 0 )
  414.         {
  415.             logerror("VLM5030 BSY=H\n" );
  416.             /* pin_BSY = 1; */
  417.             phase = PH_WAIT;
  418.         }
  419.         break;
  420.     case PH_STOP:
  421.         sample_count -= length;
  422.         if( sample_count <= 0 )
  423.         {
  424.             logerror("VLM5030 BSY=L\n" );
  425.             pin_BSY = 0;
  426.             phase = PH_IDLE;
  427.         }
  428.     }
  429.     /* silent buffering */
  430.     while (length > 0)
  431.     {
  432.         buffer[buf_count++] = 0x00;
  433.         length--;
  434.     }
  435. }
  436.  
  437. /* realtime update */
  438. static void VLM5030_update(void)
  439. {
  440.     if( !sampling_mode )
  441.     {
  442.         /* docode mode */
  443.         stream_update(channel,0);
  444.     }
  445.     else
  446.     {
  447.         /* sampling mode (check  busy flag) */
  448.         if( pin_ST == 0 && pin_BSY == 1 )
  449.         {
  450.             if( !mixer_is_sample_playing(schannel) )
  451.                 pin_BSY = 0;
  452.         }
  453.     }
  454. }
  455.  
  456. /* set speech rom address */
  457. void VLM5030_set_rom(void *speech_rom)
  458. {
  459.     VLM5030_rom = speech_rom;
  460. }
  461.  
  462. /* get BSY pin level */
  463. int VLM5030_BSY(void)
  464. {
  465.     VLM5030_update();
  466.     return pin_BSY;
  467. }
  468.  
  469. /* latch contoll data */
  470. WRITE_HANDLER( VLM5030_data_w )
  471. {
  472.     latch_data = data;
  473. }
  474.  
  475. /* set RST pin level : reset / set table address A8-A15 */
  476. void VLM5030_RST (int pin )
  477. {
  478.     if( pin_RST )
  479.     {
  480.         if( !pin )
  481.         {    /* H -> L : latch high address table */
  482.             pin_RST = 0;
  483. /*            table_h = latch_data * 256; */
  484.             table_h = 0;
  485.         }
  486.     }
  487.     else
  488.     {
  489.         if( pin )
  490.         {    /* L -> H : reset chip */
  491.             pin_RST = 1;
  492.             if( pin_BSY )
  493.             {
  494.                 if( sampling_mode )
  495.                     mixer_stop_sample( schannel );
  496.                 phase = PH_RESET;
  497.                 pin_BSY = 0;
  498.             }
  499.         }
  500.     }
  501. }
  502.  
  503. /* set VCU pin level : ?? unknown */
  504. void VLM5030_VCU(int pin)
  505. {
  506.     /* unknown */
  507. /*    intf->vcu = pin; */
  508.     return;
  509. }
  510.  
  511. /* set ST pin level  : set table address A0-A7 / start speech */
  512. void VLM5030_ST(int pin )
  513. {
  514.     int table = table_h | latch_data;
  515.  
  516.     if( pin_ST != pin )
  517.     {
  518.         /* pin level is change */
  519.         if( !pin )
  520.         {    /* H -> L */
  521.             pin_ST = 0;
  522.             /* start speech */
  523.  
  524.             if (Machine->sample_rate == 0)
  525.             {
  526.                 pin_BSY = 0;
  527.                 return;
  528.             }
  529.             /* set play mode samplingfile or emulate */
  530.             sampling_mode = check_samplefile(table/2);
  531.             if( !sampling_mode )
  532.             {
  533.                 VLM5030_update();
  534.  
  535.                 logerror("VLM5030 %02X start adr=%04X\n",table/2,VLM5030_address );
  536.  
  537.                 /* docode mode */
  538.                 VLM5030_address = (((int)VLM5030_rom[table&VLM5030_address_mask])<<8)
  539.                                 |        VLM5030_rom[(table+1)&VLM5030_address_mask];
  540.                 /* reset process status */
  541.                 interp_count = sample_count = 0;
  542.                 /* clear filter */
  543.                 /* after 3 sampling start */
  544.                 phase = PH_RUN;
  545.             }
  546.             else
  547.             {
  548.                 /* sampling mode */
  549.                 int num = table>>1;
  550.  
  551.                 mixer_play_sample(schannel,
  552.                     Machine->samples->sample[num]->data,
  553.                     Machine->samples->sample[num]->length,
  554.                     Machine->samples->sample[num]->smpfreq,
  555.                     0);
  556.             }
  557.         }
  558.         else
  559.         {    /* L -> H */
  560.             pin_ST = 1;
  561.             /* setup speech , BSY on after 30ms? */
  562.             phase = PH_SETUP;
  563.             sample_count = 1; /* wait time for busy on */
  564.             pin_BSY = 1; /* */
  565.         }
  566.     }
  567. }
  568.  
  569. /* start VLM5030 with sound rom              */
  570. /* speech_rom == 0 -> use sampling data mode */
  571. int VLM5030_sh_start(const struct MachineSound *msound)
  572. {
  573.     int emulation_rate;
  574.  
  575.     intf = msound->sound_interface;
  576.  
  577.     Machine->samples = readsamples(intf->samplenames,Machine->gamedrv->name);
  578.  
  579.     emulation_rate = intf->baseclock / 440;
  580.     pin_BSY = pin_RST = pin_ST  = 0;
  581.     phase = PH_IDLE;
  582. /*    VLM5030_VCU(intf->vcu); */
  583.  
  584.     VLM5030_rom = memory_region(intf->memory_region);
  585.     /* memory size */
  586.     if( intf->memory_size == 0)
  587.         VLM5030_address_mask = memory_region_length(intf->memory_region)-1;
  588.     else
  589.         VLM5030_address_mask = intf->memory_size-1;
  590.  
  591.     channel = stream_init("VLM5030",intf->volume,emulation_rate /* Machine->sample_rate */,
  592.                 0,vlm5030_update_callback);
  593.     if (channel == -1) return 1;
  594.  
  595.     schannel = mixer_allocate_channel(intf->volume);
  596.  
  597. #if 1
  598.     {
  599.     int i;
  600.  
  601.     /* initialize energy table */
  602.     for(i=0;i<0x20;i++)
  603.     {
  604.         energytable[i]=0x7fff*i/0x1f;
  605.     }
  606.  
  607.     /* initialize filter table */
  608.     for(i=-0x40 ; i<0x40 ; i++)
  609.     {
  610.         k1table[(i>=0) ? i : i+0x80] = i*K1_RANGE/0x40;
  611.     }
  612.     for(i=-0x08 ; i<0x08 ; i++)
  613.     {
  614.         k2table[(i>=0) ? i : i+0x10] = i*K2_RANGE/0x08;
  615.         k3table[(i>=0) ? i : i+0x10] = i*K3_RANGE/0x08;
  616.         k4table[(i>=0) ? i : i+0x10] = i*K4_RANGE/0x08;
  617.     }
  618.     for(i=-0x04 ; i<0x04 ; i++)
  619.     {
  620.         k5table[(i>=0) ? i : i+0x08] = i*K5_RANGE/0x04;
  621.         k6table[(i>=0) ? i : i+0x08] = i*K6_RANGE/0x04;
  622.         k7table[(i>=0) ? i : i+0x08] = i*K7_RANGE/0x04;
  623.         k8table[(i>=0) ? i : i+0x08] = i*K8_RANGE/0x04;
  624.         k9table[(i>=0) ? i : i+0x08] = i*K9_RANGE/0x04;
  625.         k10table[(i>=0) ? i : i+0x08] = i*K10_RANGE/0x04;
  626.     }
  627.  
  628.     }
  629. #endif
  630.     return 0;
  631. }
  632.  
  633. /* update VLM5030 */
  634. void VLM5030_sh_update( void )
  635. {
  636.     VLM5030_update();
  637. }
  638.  
  639. /* stop VLM5030 */
  640. void VLM5030_sh_stop( void )
  641. {
  642. }
  643.